package com.cw.jeeyt.core.impl.facadeExcel;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.cw.jeeyt.common.enums.EnumYn;
import com.cw.jeeyt.core.intf.facadeExcel.JavaDocReaderCore;
import com.cw.jeeyt.api.dto.facadeExcel.ApiCommonContent;
import com.cw.jeeyt.api.dto.facadeExcel.ApiEnum;
import com.cw.jeeyt.api.dto.facadeExcel.ApiFacade;
import com.cw.jeeyt.api.dto.facadeExcel.ApiGenerateFacadeExcelDto;
import com.cw.jeeyt.api.dto.facadeExcel.ApiMethod;
import com.cw.jeeyt.api.dto.facadeExcel.ApiParam;
import com.cw.jeeyt.api.dto.facadeExcel.ApiParamField;
import com.cw.jeeyt.api.dto.facadeExcel.FacadeFileInfo;
import com.cw.jeeyt.api.enums.EnumAskType;
import com.cw.jeeyt.api.enums.EnumCommonParam;
import com.cw.jeeyt.api.enums.EnumParamType;
import com.sun.javadoc.AnnotationDesc;
import com.sun.javadoc.ClassDoc;
import com.sun.javadoc.FieldDoc;
import com.sun.javadoc.LanguageVersion;
import com.sun.javadoc.MethodDoc;
import com.sun.javadoc.Parameter;
import com.sun.javadoc.ParameterizedType;
import com.sun.javadoc.RootDoc;
import com.sun.javadoc.Type;

/**
 * java注释读取工具类
 *
 * @author chenw
 */
@Service
public class JavaDocReaderCoreImpl implements JavaDocReaderCore {
    private static Logger logger = LoggerFactory.getLogger(JavaDocReaderCoreImpl.class);

    @Autowired
    private MyClassLoader myClassLoader;
    @Value("${swiftAnnotationPath}")
    private String swiftAnnotationPath;
    /**
     * 响应参数里面的对象
     */
    private static List<ApiParam> fieldResponseParams;
    private static List<ApiParam> fieldRequestParams;
    private static List<ApiParam> checkRequestParams;
    private static List<ApiParam> checkResponseParams;
    private static List<ApiEnum> enums;
    /**
     * 所有要生成文档的接口文件信息
     */
    private static List<FacadeFileInfo> facadeFileList = new ArrayList<>();
    /**
     * 所有要生成文档的接口参数文件信息
     */
    private static List<FacadeFileInfo> facadeParamFileList = new ArrayList<>();

    /**
     * 接口文件路径
     */
    private static String facadeFilePaths = "";
    /**
     * 接口参数文件路径
     */
    private static String facadeParamFilePaths = "";
    /**
     * class文件目录
     */
    private static String targetPath = "";
    /** 枚举类文件路径 */
    private static String enumClassPath = "";
    /**
     * java文件路径
     */
    private static String filePath = "";
    /**
     * java文件全路径
     */
    private static String fileFullPath = "";
    /**
     * 接口文档
     */
    private static ApiFacade apiFacade;
    /**
     * 类信息
     */
    private static Map<String, Class> classFileInfos;
    /**
     * 是否添加公共枚举
     */
    private static boolean addCommonEnum = false;

    private static RootDoc root;

    /**
     * 获取接口信息
     *
     * @return
     */
    @Override
    public List<ApiFacade> getFacadeInfo(ApiGenerateFacadeExcelDto facadeExcelDto) {
        facadeFileList = new ArrayList<>();
        facadeParamFileList = new ArrayList<>();
        fieldResponseParams = new ArrayList<>();
        fieldRequestParams = new ArrayList<>();
        checkRequestParams = new ArrayList<>();
        checkResponseParams = new ArrayList<>();
        enums = new ArrayList<>();
        classFileInfos = new HashMap<>();
        targetPath = facadeExcelDto.getTargetPath() + ";" + swiftAnnotationPath;
        List<ApiFacade> apiFacades = new ArrayList<>();
        facadeFilePaths = facadeExcelDto.getFacadeFilePaths();
        //获取所有接口文件
        getFileList(facadeFilePaths, "facade");
        //获取所有接口参数文件
        facadeParamFilePaths = facadeExcelDto.getFacadeParamFilePaths();
        getFileList(facadeParamFilePaths, "facadeParam");
        enumClassPath = facadeExcelDto.getTargetPath();
        classFileInfos = myClassLoader.findClassesByLocation(facadeExcelDto.getTargetPath(), enumClassPath, ".class",
            facadeExcelDto.getEnumPatterns(), facadeExcelDto.getEnumSacnPackage());
        if (facadeFileList != null && !facadeFileList.isEmpty()) {
            int i = 1;
            for (FacadeFileInfo facadeFileInfo : facadeFileList) {
                fileFullPath = facadeFileInfo.getFacadeFullPath();
                executeJavaDoc(targetPath, fileFullPath);
                ApiFacade apiFacade = initDocInfo(facadeExcelDto);
                if (apiFacade == null) {
                    continue;
                }
                apiFacade.setFacadeNum(i);
                apiFacades.add(apiFacade);
                i++;
            }
        }
        return apiFacades;
    }

    /**
     * 初始化公共报文
     *
     * @return
     */
    @Override
    public ApiCommonContent getCommonParams(ApiGenerateFacadeExcelDto facadeExcelDto) {
        addCommonEnum = true;
        targetPath = facadeExcelDto.getTargetPath();
        enums = new ArrayList<>();
        ApiCommonContent apiCommonContent = new ApiCommonContent();
        List<ApiParam> apiParams = initCommonParams();
        List<ApiParam> commonRequestParams = new ArrayList<>();
        List<ApiParam> commonResponseParams = new ArrayList<>();
        for (ApiParam apiParam : apiParams) {
            String apiParamFulePath = apiParam.getParamFullPath();
            apiParamFulePath = apiParamFulePath.replace(".", "\\");
            filePath = targetPath + "\\" + apiParamFulePath + ".java";
            executeJavaDoc(targetPath, filePath);
            apiParam.setFields(initParamFieldInfo(apiParam.getParamType(), true));
            if (EnumParamType.COMMONREQUEST.getCode()
                .equals(apiParam.getParamType())) {
                apiParam.setParamCode(apiParam.getHeaderName());
                commonRequestParams.add(apiParam);
            } else {
                commonResponseParams.add(apiParam);
            }
        }
        apiCommonContent.setCommonRequestParams(commonRequestParams);
        apiCommonContent.setCommonResponseParams(commonResponseParams);
        if (enums != null && !enums.isEmpty()) {
            // List<String> jarFilePaths = new ArrayList<>();
            // String enumJarPaths = ResourceUtil.getValue("enumJarPaths");
            // String[] enumJarPathList = enumJarPaths.split(",");
            // if (enumJarPathList != null && enumJarPathList.length > 0) {
            //     for (String enumJarPath : enumJarPathList) {
            //         jarFilePaths.add(enumJarPath);
            //     }
            // }
            apiCommonContent.setApiEnumList(EnumAnalysisCore.analysisEnum(classFileInfos, enums));
        }
        return apiCommonContent;
    }

    // 一个简单Doclet,收到 RootDoc对象保存起来供后续使用
    // 参见参考资料6
    public static class Doclet extends com.sun.javadoc.Doclet {

        public Doclet() {
        }

        public static boolean start(RootDoc root) {
            JavaDocReaderCoreImpl.root = root;
            return true;
        }

        public static LanguageVersion languageVersion() {
            return LanguageVersion.JAVA_1_5;
        }
    }

    // 显示DocRoot中的基本信息
    private ApiFacade initDocInfo(ApiGenerateFacadeExcelDto facadeExcelDto) {
        apiFacade = new ApiFacade();
        //都是单个文件处理，所以只取第一条数据
        ClassDoc[] classDocs = root.classes();
        if (classDocs == null || classDocs.length == 0) {
            return null;
        }
        ClassDoc docClass = root.classes()[0];
        String facadeCode = docClass.typeName();
        apiFacade.setFacadeCode(facadeCode);
        apiFacade.setFacadeName(docClass.commentText());
        List<ApiMethod> apiMethods = new ArrayList<>();
        //方法
        for (MethodDoc method : docClass.methods()) {
            fieldResponseParams = new ArrayList<>();
            fieldRequestParams = new ArrayList<>();
            checkRequestParams = new ArrayList<>();
            checkResponseParams = new ArrayList<>();
            enums = new ArrayList<>();
            ApiMethod apiMethod = new ApiMethod();
            apiMethod.setMethodCode(method.name());
            apiMethod.setMethodName(method.commentText());
            String methodUrl = getMethodHttpUrl(method);
            if (StringUtils.isEmpty(methodUrl)) {
                methodUrl = facadeExcelDto.getFacadeUrlPrefix() + "/" + getLowerCaseCode(facadeCode) + "/"
                    + method.name();
            } else {
                methodUrl = facadeExcelDto.getFacadeUrlPrefix() + "/" + getLowerCaseCode(facadeCode) + methodUrl;
            }
            apiMethod.setMethodUrl(methodUrl);
            apiMethod.setAskType(getMethodAskType(method));
            //获取方法的请求对象
            apiMethod.setRequestParams(getMethodRequestObj(method));
            //获取方法的返回对象
            apiMethod.setResponseParams(getMethodReturnObj(method));
            apiMethod.setFieldRequestParams(fieldRequestParams);
            apiMethod.setFieldResponseParams(fieldResponseParams);
            if (enums != null && !enums.isEmpty()) {
                apiMethod.setEnums(EnumAnalysisCore.analysisEnum(classFileInfos, enums));
            }
            apiMethods.add(apiMethod);
        }
        apiFacade.setMethods(apiMethods);
        logger.info("{}接口文档信息：{}", apiFacade.getFacadeCode(), JSON.toJSONString(apiFacade));
        return apiFacade;
    }

    /**
     * 首字母小写
     *
     * @param facadeCode
     * @return
     */
    private static String getLowerCaseCode(String facadeCode) {
        if (StringUtils.isEmpty(facadeCode)) {
            return "";
        }
        if (facadeCode.contains("Controller")) {
            facadeCode = facadeCode.replace("Controller", "");
        } else {
            facadeCode = facadeCode.substring(1);
        }
        facadeCode = facadeCode.replaceFirst(facadeCode.substring(0, 1), facadeCode.substring(0, 1)
            .toLowerCase());
        return facadeCode;
    }

    private static String getMethodAskType(MethodDoc method) {
        AnnotationDesc[] annotationDescs = method.annotations();
        for (AnnotationDesc annotationDesc : annotationDescs) {
            logger.info(annotationDesc.annotationType()
                .toString());
            for (EnumAskType enumAskType : EnumAskType.values()) {
                if (annotationDesc.annotationType()
                    .toString()
                    .contains(enumAskType.getDesc())) {
                    return enumAskType.getCode();
                }
            }
        }
        return EnumAskType.POST.getCode();
    }

    private static String getMethodHttpUrl(MethodDoc method) {
        AnnotationDesc[] annotationDescs = method.annotations();
        for (AnnotationDesc annotationDesc : annotationDescs) {
            logger.info(annotationDesc.annotationType()
                .toString());
            for (EnumAskType enumAskType : EnumAskType.values()) {
                if (annotationDesc.annotationType()
                    .toString()
                    .contains(enumAskType.getDesc())) {
                    return annotationDesc.elementValues()[0].value()
                        .toString()
                        .replace("\"", "");
                }
            }
        }
        return null;
    }

    /**
     * 获取方法请求对象
     *
     * @param method
     * @return
     */
    private static List<ApiParam> getMethodRequestObj(MethodDoc method) {
        List<ApiParam> apiParams = new ArrayList<>();
        Parameter[] parameters = method.parameters();
        if (parameters != null && parameters.length > 0) {
            for (Parameter param : parameters) {
                if (param.type()
                    .asParameterizedType() != null) {
                    StringBuilder fieldTypeStr = new StringBuilder("");
                    String docType = param.type()
                        .typeName();
                    FacadeFileInfo docFileInfo = findFacadePojoInfo(docType);
                    if (docFileInfo != null) {
                        ApiParam apiParam = new ApiParam();
                        apiParam.setParamCode(docFileInfo.getFacadeCode());
                        apiParam.setParamFullPath(docFileInfo.getFacadeFullPath());
                        apiParams.add(apiParam);
                    }
                    String pType = getFieldType(param.type(), fieldTypeStr);
                    String paramCode = pType.substring(pType.lastIndexOf(".") + 1);
                    //字段类型
                    FacadeFileInfo facadeFileInfo = findFacadePojoInfo(paramCode);
                    if (facadeFileInfo != null) {
                        ApiParam apiParam = new ApiParam();
                        apiParam.setParamCode(facadeFileInfo.getFacadeCode());
                        apiParam.setParamFullPath(facadeFileInfo.getFacadeFullPath());
                        apiParams.add(apiParam);
                    } else {
                        if (paramCode.startsWith("Enum")) {
                            ApiEnum apiEnum = new ApiEnum();
                            apiEnum.setInit(false);
                            apiEnum.setEnumCode(paramCode);
                            apiEnum.setClassName(pType);
                            if (!checkEnumsExist(enums, paramCode)) {
                                enums.add(apiEnum);
                            }
                        }
                    }
                } else {
                    ApiParam apiParam = new ApiParam();
                    apiParam.setParamCode(param.typeName());
                    apiParam.setParamName(param.name());
                    apiParam.setParamFullPath(param.type()
                        .toString());
                    apiParams.add(apiParam);
                }
            }
        }
        if (apiParams != null && !apiParams.isEmpty()) {
            getParamFieldInfo(apiParams, EnumParamType.REQUEST.getCode());
        }
        return apiParams;
    }

    /**
     * 添加header请求参数
     */
    private static List<ApiParam> initCommonParams() {
        List<ApiParam> apiParams = new ArrayList<>();
        //添加hsjryRequest
        ApiParam apiParam = new ApiParam();
        apiParam.setParamCode(EnumCommonParam.BASEREQUEST.getCode());
        apiParam.setHeaderName(EnumCommonParam.BASEREQUEST.getHeaderName());
        apiParam.setParamName(EnumCommonParam.BASEREQUEST.getDesc());
        apiParam.setParamFullPath(EnumCommonParam.BASEREQUEST.getFullPath());
        apiParam.setParamType(EnumParamType.COMMONREQUEST.getCode());
        apiParams.add(apiParam);

        //添加hsjryUserRequest
        ApiParam apiRequestParam = new ApiParam();
        apiRequestParam.setParamCode(EnumCommonParam.BASERUSEREQUEST.getCode());
        apiRequestParam.setHeaderName(EnumCommonParam.BASERUSEREQUEST.getHeaderName());
        apiRequestParam.setParamName(EnumCommonParam.BASERUSEREQUEST.getDesc());
        apiRequestParam.setParamFullPath(EnumCommonParam.BASERUSEREQUEST.getFullPath());
        apiRequestParam.setParamType(EnumParamType.COMMONREQUEST.getCode());
        apiParams.add(apiRequestParam);

        //添加CommonResponse
        ApiParam apiCommonResponse = new ApiParam();
        apiCommonResponse.setParamCode(EnumCommonParam.COMMONRESPONSE.getCode());
        apiCommonResponse.setParamName(EnumCommonParam.COMMONRESPONSE.getDesc());
        apiCommonResponse.setParamFullPath(EnumCommonParam.COMMONRESPONSE.getFullPath());
        apiCommonResponse.setParamType(EnumParamType.COMMONRESPONSE.getCode());
        apiParams.add(apiCommonResponse);
        return apiParams;
    }

    /**
     * 添加父类param
     */
    private static void addSuperClassParam(String paramType) {
        ClassDoc classDoc = root.classes()[0].superclass();
        List<ApiParam> superParams = new ArrayList<>();
        if (classDoc != null && !"Object".equals(classDoc.name()) && !classDoc.name()
            .startsWith("Enum")) {
            String paramCode = classDoc.name();
            FacadeFileInfo facadeFileInfo = findFacadePojoInfo(paramCode);
            ApiParam apiParam = new ApiParam();
            apiParam.setParamType(classDoc.typeName());
            apiParam.setParamCode(classDoc.name());
            apiParam.setParamFullPath(facadeFileInfo.getFacadeFullPath());
            superParams.add(apiParam);
        }
        if (superParams != null && !superParams.isEmpty()) {
            getParamFieldInfo(superParams, paramType);
            if (EnumParamType.REQUEST.getCode()
                .equals(paramType)) {
                fieldRequestParams.addAll(superParams);
            } else if (EnumParamType.RESPONSE.getCode()
                .equals(paramType)) {
                fieldResponseParams.addAll(superParams);
            }
        }
    }

    /**
     * 校验当前方法的参数是否已存在
     *
     * @param apiParam
     * @return
     */
    private static boolean checkParam(ApiParam apiParam, String paramType) {
        boolean isExist = false;
        if (paramType.equals(EnumParamType.REQUEST.getCode())) {
            if (checkRequestParams == null || checkRequestParams.isEmpty()) {
                checkRequestParams.add(apiParam);
                return false;
            }
            for (ApiParam checkApiParam : checkRequestParams) {
                if (checkApiParam.getParamFullPath()
                    .equals(apiParam.getParamFullPath())) {
                    isExist = true;
                    break;
                }
            }
            if (!isExist) {
                checkRequestParams.add(apiParam);
            }
        } else if (paramType.equals(EnumParamType.RESPONSE.getCode())) {
            if (checkResponseParams == null || checkResponseParams.isEmpty()) {
                checkResponseParams.add(apiParam);
                return false;
            }
            for (ApiParam checkApiParam : checkResponseParams) {
                if (checkApiParam.getParamFullPath()
                    .equals(apiParam.getParamFullPath())) {
                    isExist = true;
                    break;
                }
            }
            if (!isExist) {
                checkResponseParams.add(apiParam);
            }
        }
        return isExist;
    }

    /**
     * 获取方法返回对象
     *
     * @param method
     * @return
     */
    private static List<ApiParam> getMethodReturnObj(MethodDoc method) {
        List<ApiParam> apiParams = new ArrayList<ApiParam>();
        ParameterizedType parameterizedType = method.returnType()
            .asParameterizedType();
        if (parameterizedType != null) {
            //递归添加参数
            recursiveApiParam(method.returnType(), apiParams, EnumParamType.RESPONSE);
        } else {
            String typeName = method.returnType()
                .typeName();
            FacadeFileInfo facadeFileInfo = findFacadePojoInfo(typeName);
            if (facadeFileInfo != null) {
                ApiParam apiParam = new ApiParam();
                apiParam.setParamFullPath(facadeFileInfo.getFacadeFullPath());
                apiParam.setParamCode(facadeFileInfo.getFacadeCode());
                apiParam.setParamName(facadeFileInfo.getFacadeName());
                apiParam.setParamType(typeName);
                apiParams.add(apiParam);
            }
        }
        if (apiParams != null && !apiParams.isEmpty()) {
            getParamFieldInfo(apiParams, EnumParamType.RESPONSE.getCode());
        }
        return apiParams;
    }

    /**
     * 递归获取参数
     *
     * @param type
     * @param apiParams
     */
    private static void recursiveApiParam(Type type, List<ApiParam> apiParams, EnumParamType paramType) {
        ParameterizedType parameterizedType = type.asParameterizedType();
        if (parameterizedType.asParameterizedType() != null) {
            FacadeFileInfo docFileInfo = findFacadePojoInfo(parameterizedType.asParameterizedType()
                .typeName());
            if (docFileInfo != null) {
                ApiParam apiParam = new ApiParam();
                apiParam.setParamCode(docFileInfo.getFacadeCode());
                apiParam.setParamFullPath(docFileInfo.getFacadeFullPath());
                if (!checkParam(apiParam, paramType.getCode())) {
                    apiParams.add(apiParam);
                }
            }
        }
        Type[] types = parameterizedType.typeArguments();
        for (Type subType : types) {
            if (subType.toString()
                .contains("Void")) {
                continue;
            }
            ParameterizedType subParameterizedType = subType.asParameterizedType();
            if (subParameterizedType != null) {
                recursiveApiParam(subType, apiParams, paramType);
            } else {
                ApiParam apiParam = new ApiParam();
                apiParam.setParamFullPath(subType.toString());
                apiParam.setParamCode(subType.typeName());
                if (!checkParam(apiParam, paramType.getCode())) {
                    apiParams.add(apiParam);
                }
            }
        }
    }

    /**
     * 初始化方法参数属性
     *
     * @param apiParams 参数集合
     */
    private static void getParamFieldInfo(List<ApiParam> apiParams, String paramType) {
        for (ApiParam apiParam : apiParams) {
            String paramCode = apiParam.getParamCode();
            FacadeFileInfo facadeFileInfo = findFacadePojoInfo(paramCode);
            if (facadeFileInfo == null) {
                continue;
            }
            filePath = facadeFileInfo.getFacadeFullPath();
            boolean isCommonObject = false;
            if (EnumCommonParam.find(apiParam.getParamCode()) != null) {
                if (EnumParamType.REQUEST.getCode()
                    .equals(paramType)) {
                    apiParam.setParamType(EnumParamType.COMMONREQUEST.getCode());
                } else if (EnumParamType.RESPONSE.getCode()
                    .equals(paramType)) {
                    apiParam.setParamType(EnumParamType.COMMONRESPONSE.getCode());
                }
                isCommonObject = true;
            } else {
                apiParam.setParamType(paramType);
            }
            executeJavaDoc(targetPath, filePath);
            apiParam.setFields(initParamFieldInfo(paramType, isCommonObject));
        }
    }

    /**
     * 查找facade pojo参数
     *
     * @param paramCode
     * @return
     */
    private static FacadeFileInfo findFacadePojoInfo(String paramCode) {
        if (facadeParamFileList != null && !facadeParamFileList.isEmpty()) {
            for (FacadeFileInfo facadeFileInfo : facadeParamFileList) {
                String fileCode = facadeFileInfo.getFacadeCode();
                if (fileCode.equals(paramCode)) {
                    return facadeFileInfo;
                }
            }
        }
        return null;
    }

    /**
     * 初始化参数属性信息
     */
    private static List<ApiParamField> initParamFieldInfo(String paramType, boolean isCommonObject) {
        //都是单个文件处理，所以只取第一条数据
        //ClassDoc[] classes = root.classes();
        //for (int i = 0; i < classes.length; ++i) {
        List<ApiParam> paramList = new ArrayList<>();
        List<ApiParamField> fields = new ArrayList<>();
        for (FieldDoc fieldDoc : root.classes()[0].serializableFields()) {
            ApiParamField apiParamField = new ApiParamField();
            //字段名称
            apiParamField.setFieldCode(fieldDoc.name());
            //字段注释
            apiParamField.setFieldName(fieldDoc.commentText());

            //判断是否为空
            AnnotationDesc[] annotationDescs = fieldDoc.annotations();

            apiParamField.setIsRequired(EnumYn.N.getCode());
            if (annotationDescs != null && annotationDescs.length > 0) {
                boolean isRequired = false;
                for (AnnotationDesc annotationDesc : annotationDescs) {
                    String annotationType = annotationDesc.annotationType()
                        .typeName();
                    if (annotationType.contains("NotNull") || annotationType.contains("NotBlank")) {
                        isRequired = true;
                    }
                }
                if (isRequired) {
                    apiParamField.setIsRequired(EnumYn.Y.getCode());
                }
            }
            //如果对象是数组或Map,fieldType需要组装
            StringBuilder fieldTypeStr = new StringBuilder("");
            String docType = fieldDoc.type()
                .typeName();
            if (fieldDoc.type()
                .asParameterizedType() != null) {
                String pType = getFieldType(fieldDoc.type(), fieldTypeStr);
                String paramCode = pType.substring(pType.lastIndexOf(".") + 1);
                //字段类型
                apiParamField.setFieldType(fieldTypeStr.toString());
                FacadeFileInfo facadeFileInfo = findFacadePojoInfo(paramCode);
                if (facadeFileInfo != null) {
                    ApiParam apiParam = new ApiParam();
                    apiParam.setParamCode(facadeFileInfo.getFacadeCode());
                    apiParam.setParamFullPath(facadeFileInfo.getFacadeFullPath());
                    if (!checkParam(apiParam, paramType)) {
                        paramList.add(apiParam);
                    }
                } else {
                    if (paramCode.startsWith("Enum")) {
                        if (addCommonEnum == false && isCommonObject) {
                            continue;
                        }
                        ApiEnum apiEnum = new ApiEnum();
                        apiEnum.setInit(false);
                        apiEnum.setEnumCode(paramCode);
                        apiEnum.setClassName(pType);
                        if (!checkEnumsExist(enums, paramCode)) {
                            enums.add(apiEnum);
                        }
                    }
                }
            } else {
                FacadeFileInfo facadeFileInfo = findFacadePojoInfo(docType);
                if (facadeFileInfo != null && !docType.startsWith("Enum")) {
                    ApiParam apiParam = new ApiParam();
                    apiParam.setParamCode(facadeFileInfo.getFacadeCode());
                    apiParam.setParamFullPath(facadeFileInfo.getFacadeFullPath());
                    if (!checkParam(apiParam, paramType)) {
                        paramList.add(apiParam);
                    }
                    //字段类型
                    apiParamField.setFieldType(fieldDoc.type()
                        .typeName());
                } else {
                    //字段类型
                    apiParamField.setFieldType(fieldDoc.type()
                        .typeName());
                    //方法添加枚举
                    if (docType.startsWith("Enum")) {
                        if (addCommonEnum == false && isCommonObject) {
                            continue;
                        }
                        ApiEnum apiEnum = new ApiEnum();
                        apiEnum.setInit(false);
                        apiEnum.setEnumCode(docType);
                        apiEnum.setEnumDesc(fieldDoc.commentText());
                        apiEnum.setClassName(fieldDoc.type()
                            .qualifiedTypeName());
                        if (!checkEnumsExist(enums, docType)) {
                            enums.add(apiEnum);
                        }
                    }
                }
            }
            fields.add(apiParamField);
        }
        //}
        if (paramList != null && !paramList.isEmpty()) {
            initPojoParam(paramList, paramType, isCommonObject);
        }
        return fields;
    }

    private static String getFieldType(Type type, StringBuilder fieldTypeStr) {
        String pType = "";
        String typeName = type.typeName();
        ParameterizedType genericType = type.asParameterizedType();
        Type[] types = genericType.typeArguments();
        int i = 0;
        boolean hasSubType = false;
        fieldTypeStr.append(typeName + "<");
        for (Type subType : types) {
            if (subType.asParameterizedType() != null) {
                pType = getFieldType(subType, fieldTypeStr);
                hasSubType = true;
            } else {
                pType = subType.toString();
            }
            String fieldType = pType.substring(pType.lastIndexOf(".") + 1, pType.length());
            if (type.typeName()
                .contains("Map") && !hasSubType) {
                if (i == 0) {
                    fieldTypeStr.append(fieldType + ",");
                } else {
                    fieldTypeStr.append(fieldType);
                }
            } else {
                if (!type.typeName()
                    .contains("Map")) {
                    fieldTypeStr.append(fieldType);
                }
            }
            i++;
        }
        fieldTypeStr.append(">");
        return pType;
    }

    /**
     * 检查是否存在
     *
     * @param enums
     * @param paramCode
     * @return
     */
    private static boolean checkEnumsExist(List<ApiEnum> enums, String paramCode) {
        if (CollectionUtils.isNotEmpty(enums)) {
            for (ApiEnum apiEnum : enums) {
                if (apiEnum.getEnumCode()
                    .equals(paramCode)) {
                    return true;
                }
            }
        }
        return false;
    }

    private static void initPojoParam(List<ApiParam> paramList, String paramType, boolean isCommonObject) {
        for (ApiParam apiParam : paramList) {
            filePath = apiParam.getParamFullPath();
            if (EnumCommonParam.find(apiParam.getParamCode()) != null) {
                if (EnumParamType.REQUEST.getCode()
                    .equals(paramType)) {
                    apiParam.setParamType(EnumParamType.COMMONREQUEST.getCode());
                } else if (EnumParamType.RESPONSE.getCode()
                    .equals(paramType)) {
                    apiParam.setParamType(EnumParamType.COMMONRESPONSE.getCode());
                }
            } else {
                apiParam.setParamType(paramType);
            }
            executeJavaDoc(targetPath, filePath);
            addSuperClassParam(paramType);
            //添加完父类class再执行一遍javadoc
            filePath = apiParam.getParamFullPath();
            executeJavaDoc(targetPath, filePath);
            apiParam.setFields(initParamFieldInfo(paramType, isCommonObject));
            if (EnumParamType.REQUEST.getCode()
                .equals(paramType)) {
                fieldRequestParams.add(apiParam);
            } else if (EnumParamType.RESPONSE.getCode()
                .equals(paramType)) {
                fieldResponseParams.add(apiParam);
            }
        }
    }

    public static RootDoc getRoot() {
        return root;
    }

    public JavaDocReaderCoreImpl() {

    }

    public static void executeJavaDoc(String targetPath, String fileFullPath) {
        // 调用com.sun.tools.javadoc.Main执行javadoc,参见 参考资料3
        // javadoc的调用参数，参见 参考资料1
        // -doclet 指定自己的docLet类名
        // -classpath 参数指定 源码文件及依赖库的class位置，不提供也可以执行，但无法获取到完整的注释信息(比如annotation)
        // -encoding 指定源码文件的编码格式
        com.sun.tools.javadoc.Main.execute(new String[] {"-doclet", Doclet.class.getName(),
            // 因为自定义的Doclet类并不在外部jar中，就在当前类中，所以这里不需要指定-docletpath 参数，
            //"-docletpath",
            //Doclet.class.getResource("/").getPath(),
            "-encoding", "utf-8", "-classpath", targetPath,
            // 获取单个代码文件FaceLogDefinition.java的javadoc
            fileFullPath});
    }

    public static void main(final String... args) {

        //getFacadeInfo();
       /* String targetPath = "D:/yunrong_project/git/2.0.4/user/hsjry-user-facade-pojo/target/classes";
        String fileFullPath = "D:/yunrong_project/git/2.0.4/user/hsjry-user-facade-pojo/src/main/java/com/hsjry/user/facade/pojo/enums/EnumAccountType.java";
        executeJavaDoc(targetPath, fileFullPath);
        FieldDoc[] facadeDoc = root.classes()[0].enumConstants();*/
    }

    /**
     * 遍历目录下所有接口参数文件
     *
     * @param facadeParamPaths
     * @return
     */
    private static void getFileList(String facadeParamPaths, String fileType) {
        if (!StringUtils.isEmpty(facadeParamPaths)) {
            String[] facadeParams = facadeParamPaths.split(",");
            for (String facadeParamPath : facadeParams) {
                File dir = new File(facadeParamPath);
                File[] files = dir.listFiles(); // 该文件目录下文件全部放入数组
                if (files != null) {
                    for (int i = 0; i < files.length; i++) {
                        String fileName = files[i].getName();
                        if (files[i].isDirectory()) { // 判断是文件还是文件夹
                            getFileList(files[i].getAbsolutePath(), fileType); // 获取文件绝对路径
                        } else if (fileName.endsWith("java")) { // 判断文件名是否以.java
                            FacadeFileInfo facadeFileInfo = new FacadeFileInfo();
                            facadeFileInfo.setFacadeCode(files[i].getName()
                                .replace(".java", ""));
                            facadeFileInfo.setFacadeName(files[i].getName());
                            facadeFileInfo.setFacadeFullPath(files[i].getPath()
                                .replace("/", "/"));
                            facadeFileInfo.setFacadePath(files[i].getPath()
                                .replace(files[i].getName(), "")
                                .replace("/", "/"));
                            if ("facadeParam".equals(fileType)) {
                                facadeParamFileList.add(facadeFileInfo);
                            } else if ("facade".equals(fileType)) {
                                facadeFileList.add(facadeFileInfo);
                            }
                            logger.info("接口、接口参数信息：{}", JSON.toJSONString(facadeFileInfo));
                        } else {
                            continue;
                        }
                    }
                }
            }
        }
    }
}
